// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/customize_themes/chrome_customize_themes_handler.h"

#include "chrome/browser/new_tab_page/chrome_colors/chrome_colors_factory.h"
#include "chrome/browser/new_tab_page/chrome_colors/chrome_colors_service.h"
#include "chrome/browser/new_tab_page/chrome_colors/generated_colors_info.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/common/themes/autogenerated_theme_util.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/webui/resources/cr_components/customize_themes/customize_themes.mojom.h"

ChromeCustomizeThemesHandler::ChromeCustomizeThemesHandler(
    mojo::PendingRemote<customize_themes::mojom::CustomizeThemesClient>
        pending_client,
    mojo::PendingReceiver<customize_themes::mojom::CustomizeThemesHandler>
        pending_handler,
    content::WebContents* web_contents,
    Profile* profile)
    : remote_client_(std::move(pending_client)),
      receiver_(this, std::move(pending_handler)),
      web_contents_(web_contents),
      profile_(profile),
      chrome_colors_service_(
          chrome_colors::ChromeColorsFactory::GetForProfile(profile_)),
      theme_service_(ThemeServiceFactory::GetForProfile(profile_)) {
  CHECK(web_contents_);
  CHECK(profile_);
  CHECK(chrome_colors_service_);
  CHECK(theme_service_);
  theme_service_->AddObserver(this);
}

ChromeCustomizeThemesHandler::~ChromeCustomizeThemesHandler() {
  // Revert any unconfirmed theme changes.
  chrome_colors_service_->RevertThemeChangesForTab(web_contents_);
  theme_service_->RemoveObserver(this);
}

void ChromeCustomizeThemesHandler::ApplyAutogeneratedTheme(
    SkColor frame_color) {
  chrome_colors_service_->ApplyAutogeneratedTheme(frame_color, web_contents_);
}

void ChromeCustomizeThemesHandler::ApplyDefaultTheme() {
  chrome_colors_service_->ApplyDefaultTheme(web_contents_);
}

void ChromeCustomizeThemesHandler::ApplyChromeTheme(int32_t id) {
  auto* begin = std::begin(chrome_colors::kGeneratedColorsInfo);
  auto* end = std::end(chrome_colors::kGeneratedColorsInfo);
  auto* result = std::find_if(begin, end,
                              [id](const chrome_colors::ColorInfo& color_info) {
                                return color_info.id == id;
                              });
  if (result == end)
    return;
  chrome_colors_service_->ApplyAutogeneratedTheme(result->color, web_contents_);
}

void ChromeCustomizeThemesHandler::InitializeTheme() {
  UpdateTheme();
}

void ChromeCustomizeThemesHandler::GetChromeThemes(
    GetChromeThemesCallback callback) {
  std::vector<customize_themes::mojom::ChromeThemePtr> themes;
  for (const auto& color_info : chrome_colors::kGeneratedColorsInfo) {
    auto theme_colors = GetAutogeneratedThemeColors(color_info.color);
    auto theme = customize_themes::mojom::ChromeTheme::New();
    theme->id = color_info.id;
    theme->label = l10n_util::GetStringUTF8(color_info.label_id);
    auto colors = customize_themes::mojom::ThemeColors::New();
    colors->frame = theme_colors.frame_color;
    colors->active_tab = theme_colors.active_tab_color;
    colors->active_tab_text = theme_colors.active_tab_text_color;
    theme->colors = std::move(colors);
    themes.push_back(std::move(theme));
  }
  std::move(callback).Run(std::move(themes));
}

void ChromeCustomizeThemesHandler::ConfirmThemeChanges() {
  chrome_colors_service_->ConfirmThemeChanges();
}

void ChromeCustomizeThemesHandler::RevertThemeChanges() {
  chrome_colors_service_->RevertThemeChanges();
}

void ChromeCustomizeThemesHandler::OnThemeChanged() {
  UpdateTheme();
}

void ChromeCustomizeThemesHandler::UpdateTheme() {
  auto theme = customize_themes::mojom::Theme::New();

  const ui::ThemeProvider& theme_provider =
      ThemeService::GetThemeProviderForProfile(profile_);
  if (theme_service_->UsingDefaultTheme() ||
      theme_service_->UsingSystemTheme()) {
    theme->type = customize_themes::mojom::ThemeType::kDefault;
    theme->info = customize_themes::mojom::ThemeInfo::NewChromeThemeId(
        chrome_colors::kDefaultColorId);
    theme->is_forced = false;
  } else if (theme_service_->UsingExtensionTheme()) {
    theme->type = customize_themes::mojom::ThemeType::kThirdParty;
    auto info = customize_themes::mojom::ThirdPartyThemeInfo::New();
    const extensions::Extension* theme_extension =
        extensions::ExtensionRegistry::Get(profile_)
            ->enabled_extensions()
            .GetByID(theme_service_->GetThemeID());
    if (theme_extension) {
      info->id = theme_extension->id();
      info->name = theme_extension->name();
    }
    theme->info = customize_themes::mojom::ThemeInfo::NewThirdPartyThemeInfo(
        std::move(info));
    theme->is_forced = false;
  } else {
    DCHECK(theme_service_->UsingAutogeneratedTheme());
    theme->is_forced = theme_service_->UsingPolicyTheme();
    int color_id = chrome_colors::ChromeColorsService::GetColorId(
        theme->is_forced ? theme_service_->GetPolicyThemeColor()
                         : theme_service_->GetAutogeneratedThemeColor());
    if (color_id != chrome_colors::kOtherColorId) {
      theme->type = customize_themes::mojom::ThemeType::kChrome;
      theme->info =
          customize_themes::mojom::ThemeInfo::NewChromeThemeId(color_id);
    } else {
      theme->type = customize_themes::mojom::ThemeType::kAutogenerated;
      auto theme_colors = customize_themes::mojom::ThemeColors::New();
      theme_colors->frame =
          theme_provider.GetColor(ThemeProperties::COLOR_FRAME_ACTIVE);
      theme_colors->active_tab =
          theme_provider.GetColor(ThemeProperties::COLOR_NTP_BACKGROUND);
      theme_colors->active_tab_text =
          theme_provider.GetColor(ThemeProperties::COLOR_NTP_TEXT);
      theme->info =
          customize_themes::mojom::ThemeInfo::NewAutogeneratedThemeColors(
              std::move(theme_colors));
    }
  }

  remote_client_->SetTheme(std::move(theme));
}
